home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 1: Comms & Networking / Almathera Ten on Ten - Disc 1: Comms & Networking.iso / tools / www / aminet2ag / aminet2ag.c < prev    next >
C/C++ Source or Header  |  1995-04-21  |  20KB  |  806 lines

  1. /*
  2. **
  3. ** $VER: Aminet2AG.c 2.0 (06.04.95)
  4. **
  5. ** Convert AminNet INDEX files in AmigaGuide© documents.
  6. **
  7. ** Copyrigth (C) 1995 José Roberto González Rocha.
  8. **
  9. **
  10. **
  11. ** Link without any C header (c.o ...)
  12. ** Fully resident and reentrant (pure).
  13. **
  14. */
  15.  
  16. /*********************************************************************************/
  17.  
  18. #include <exec/types.h>
  19. #include <exec/nodes.h>
  20. #include <exec/lists.h>
  21. #include <exec/execbase.h>
  22. #include <exec/memory.h>
  23. #include <dos/dos.h>
  24. #include <dos/dosextens.h>
  25. #include <dos/rdargs.h>
  26. #include <dos/stdio.h>
  27. #include <workbench/startup.h>
  28.  
  29. #include <clib/dos_protos.h>
  30. #include <clib/exec_protos.h>
  31. #include <clib/utility_protos.h>
  32.  
  33. #include <pragmas/dos_pragmas.h>
  34. #include <pragmas/exec_pragmas.h>
  35. #include <pragmas/utility_pragmas.h>
  36.  
  37.  
  38.  
  39.     /* Shared data and libs                                                */
  40. struct GlobalData
  41. {
  42.     struct ExecBase       *gd_SysBase;
  43.     struct Library       *gd_DOSBase;
  44.     struct Library       *gd_UtilityBase;
  45.  
  46.     struct Process       *gd_Process;
  47.     struct WBStartup   *gd_wbMsg;
  48.     LONG                 gd_failureLevel;
  49.     LONG                 gd_failureCode;
  50.  
  51.     ULONG                 mem;
  52.     LONG                ArgArray[11];
  53.  
  54.  
  55.     BPTR                   gd_In;                /* Source INDEX file.              */
  56.     BPTR                   gd_Out;           /* Destination AmigaGuidec doc       */
  57.  
  58.     UBYTE               gd_string[100];
  59.  
  60.     WORD                 total_pending;
  61.  
  62.     WORD                root_count;        /* total file count                   */
  63.     WORD                root_dircount;    /* number of dirs.                 */
  64.     WORD                root_subcount;    /* number of subdirs.              */
  65.     LONG                root_size;        /* total size (incl. all dirs)     */
  66.     BOOL                root_ignore;    /* ignore same file size.          */
  67.     WORD                root_pending;    /* filecount of files w/o dirs.    */
  68.     struct Dir               *root_firstdir;    /* linked list head.               */
  69.     struct Dir               *root_lastdir;    /* link to the last dir            */
  70.  
  71. };
  72. #define SysBase            gd->gd_SysBase
  73. #define DOSBase            gd->gd_DOSBase
  74. #define UtilityBase        gd->gd_UtilityBase
  75.  
  76.  
  77.  
  78.     /* SubDir Nodes data                                                   */
  79.  
  80. struct SubDir
  81. {
  82.     struct SubDir *sub_next;            /* link                            */
  83.     char           sub_name[6];            /* name of this subdir.            */
  84.     WORD           sub_count;            /* file count in this subdir.      */
  85.     LONG           sub_size;            /* total size of this subdir.      */
  86.     BOOL           sub_ignore;            /* ignore same filesize.           */
  87. };
  88.  
  89.  
  90.     /* Dir Nodes data                                                      */
  91.  
  92. struct Dir
  93. {
  94.     struct Dir    *dir_next;            /* link                            */
  95.     char           dir_name[6];            /* name of this dir.               */
  96.     WORD           dir_subcount;        /* subdir count of this dir.       */
  97.     WORD           dir_count;            /* total file count of this dir    */
  98.     LONG           dir_size;            /* total size of this subdir.      */
  99.     BOOL           dir_ignore;            /* ignore same filesize            */
  100.     WORD           dir_pending;            /* file count of files w/o sub     */
  101.     struct SubDir *dir_firstsub;        /* linked list head.               */
  102.     struct SubDir *dir_lastsub;            /* link to the last subdir.        */
  103. };
  104.  
  105.  
  106. #define isnum(a) ((a >= '0') && (a <= '9'))
  107.  
  108.  
  109. /*
  110.  * Function prototipes
  111.  */
  112.  
  113. BOOL PassOne(struct GlobalData *gd, ULONG Flags);
  114. BOOL PassTwo(struct GlobalData *gd, ULONG Flags);
  115. BOOL PassThree(struct GlobalData *gd, ULONG Flags);
  116. BOOL CheckAbort(struct GlobalData *gd);
  117. VOID PrintSize(struct GlobalData *gd, LONG size, BOOL ignore);
  118.  
  119.  
  120.  
  121.  
  122. /*
  123.  * Main funcion.
  124.  * Don't use argc/argv, so why use standard main()?.
  125.  */
  126. LONG main(VOID)
  127. {
  128.     /* Version string                                                      */
  129.     char VersionString[] = "$VER: Aminet2AG 2.0 (06.04.95)";
  130.  
  131.     /* Credits                                                             */
  132.     char CopyRigthString[] = "Copyright (c) 1995 José Roberto González Rocha";
  133.  
  134.     /* Command template                                                    */
  135.     char Template[] = "FROMFILE/A,TOFILE/A,DC=DIRCOL/K/N,"
  136.                       "NT=NOTOTAL/S,NH=NOHEAD/S,NL=NOTITLE/S,"
  137.                       "TR=TITLEROW/K/N,NS=NOSTATS/S,SC=SIZECOL/K/N,"
  138.                       "P=PLAIN/S,V=VERBOSE/S";
  139.  
  140.  
  141.     struct GlobalData gdd = {NULL};
  142.     struct GlobalData *gd = &gdd;
  143.  
  144.     /* Returned object from template parsing                               */
  145.     struct RDArgs *rdargs;
  146.  
  147.     /* Position of the argument in the array                               */
  148. #define FROM_FILE 0
  149. #define TO_FILE   1
  150. #define DIRCOL    2
  151. #define NOTOTAL   3
  152. #define NOHEAD    4
  153. #define NOTITLE   5
  154. #define TITLEROW  6
  155. #define NOSTATS   7
  156. #define SIZECOL   8
  157. #define PLAIN     9
  158. #define VERBOSE   10
  159.  
  160.     /* Quick form of options, used for and'ing and or'ing                  */
  161.     REGISTER ULONG Flags = 0L;
  162. #define F_NODIR        (1L << 0)
  163. #define F_NOSUB        (1L << 1)
  164. #define F_VERBOSE    (1L << 2)
  165. #define F_NOSTATS    (1L << 3)
  166. #define F_NOTITLE    (1L << 4)
  167. #define F_NOHEAD    (1L << 5)
  168. #define F_NOTOTAL    (1L << 6)
  169. #define F_FIXDIR    (1L << 7)
  170. #define F_FIXSUB    (1L << 8)
  171. #define F_POINT       (1L << 9)
  172. #define F_NOSIZE    (1L << 10)
  173.  
  174.     gdd.gd_SysBase = *((struct ExecBase **) 4L);
  175.     gdd.gd_failureLevel = RETURN_FAIL;
  176.     gdd.gd_Process = (struct Process *) SysBase->ThisTask;
  177.     /* We only run from CLI                                                   */
  178.     if(gdd.gd_Process->pr_CLI)
  179.     {
  180.  
  181. #ifdef _M68020
  182.         /* Make sure we are running with a 68020+ CPU                      */
  183.         if (gdd.gd_SysBase->AttnFlags & AFF_68020)
  184.         {
  185. #endif
  186.             /* Open the ROM libraries                                      */
  187.             if(gdd.gd_DOSBase = OpenLibrary ("dos.library", 37L))
  188.             {
  189.                 if(gdd.gd_UtilityBase = OpenLibrary ("utility.library", 37L))
  190.                 {
  191.  
  192.                     /* Our process. Really necessary?                       */
  193.                     gdd.gd_Process = (struct Process *) FindTask (NULL);
  194.                     
  195.                     if(rdargs = ReadArgs( Template, gdd.ArgArray, NULL))
  196.                     {
  197.                         if (gdd.gd_In = Open((STRPTR)(gdd.ArgArray[FROM_FILE]), MODE_OLDFILE))
  198.                         {
  199.                             if (gdd.gd_Out = Open((STRPTR)(gdd.ArgArray[TO_FILE]), MODE_NEWFILE))
  200.                             {
  201.                                 /* Options processing                      */
  202.  
  203.                                 if(gdd.ArgArray[DIRCOL] == 0L)
  204.                                     gdd.ArgArray[DIRCOL] = 19L;
  205.                                 else
  206.                                     gdd.ArgArray[DIRCOL] = *((LONG *)(gdd.ArgArray[DIRCOL]));
  207.  
  208.                                 if(gdd.ArgArray[TITLEROW] == 0L)
  209.                                     gdd.ArgArray[TITLEROW] = 3L;
  210.                                 else
  211.                                     gdd.ArgArray[TITLEROW] = *((LONG *)(gdd.ArgArray[TITLEROW]));
  212.     
  213.                                 if(gdd.ArgArray[SIZECOL] == 0L)
  214.                                     gdd.ArgArray[SIZECOL] = 30L;
  215.                                 else
  216.                                     gdd.ArgArray[SIZECOL] = *((LONG *)(gdd.ArgArray[SIZECOL]));
  217.     
  218.     
  219.                                 if(gdd.ArgArray[VERBOSE])
  220.                                     Flags |= F_VERBOSE;
  221.     
  222.                                 if(gdd.ArgArray[PLAIN])    /* Overrides all the other flags. */
  223.                                 {
  224.                                     Flags |= F_NOHEAD | F_NOTITLE | F_NOSTATS | F_NOTOTAL;
  225.                                 }
  226.                                 else
  227.                                 {
  228.                                     if(gdd.ArgArray[NOHEAD])
  229.                                         Flags |= F_NOHEAD;
  230.     
  231.                                     if(gdd.ArgArray[NOTITLE])
  232.                                         Flags |= F_NOTITLE;
  233.     
  234.                                     if(gdd.ArgArray[NOSTATS])
  235.                                         /* If we don't want stats, why put header?       */
  236.                                         Flags |= F_NOSTATS | F_NOHEAD;
  237.     
  238.                                     if(gdd.ArgArray[NOTOTAL])
  239.                                         Flags |= F_NOTOTAL;
  240.                                 }
  241.     
  242.                                 if((Flags & (F_NOSTATS | F_NOTOTAL)) == (F_NOSTATS | F_NOTOTAL))
  243.                                     Flags |= F_NOSIZE;
  244.     
  245.     
  246.                                 if(!CheckAbort(gd))
  247.                                 {
  248.                                     if(PassOne(gd, Flags))
  249.                                         if(PassTwo(gd, Flags))
  250.                                             if(PassThree(gd, Flags))
  251.                                             {
  252.                                                 gdd.gd_failureLevel = RETURN_OK;
  253.                                                 
  254.                                                 if(Flags & F_VERBOSE)
  255.                                                 {
  256.                                                     Printf("\n\n\nAll Done!\n");
  257.                                                     Printf("\nFounds:  %5ld dirs, %5ld subdirs, %5ld files, %5ld KBytes\n",
  258.                                                            gdd.root_dircount, gdd.root_subcount,
  259.                                                            gdd.root_count, gdd.root_size);
  260.                                                 }
  261.                                             }
  262.                                     {                                    
  263.                                         struct Dir        *DirNode,*DirNode2;
  264.                                         struct SubDir  *SubDirNode,*SubDirNode2;
  265.     
  266.     
  267.                                         if(Flags & F_VERBOSE)
  268.                                             Printf( "\nUtilized %ld bytes\n", gdd.mem);
  269.  
  270.                                         /* Dealocates all memory.        */
  271.                                         gdd.mem = 0;
  272.                                         DirNode2 = gd->root_firstdir;
  273.                                         while((DirNode = DirNode2) != NULL)
  274.                                         {
  275.                                             SubDirNode2 = DirNode->dir_firstsub;
  276.                                             while((SubDirNode = SubDirNode2) != NULL)
  277.                                             {
  278.                                                 SubDirNode2 = SubDirNode->sub_next;
  279.                                                 FreeMem(SubDirNode, sizeof(struct SubDir));
  280.                                                 gdd.mem += sizeof(struct SubDir);
  281.                                             }
  282.                                             DirNode2 = DirNode->dir_next;
  283.                                             FreeMem(DirNode, sizeof(struct Dir));
  284.                                             gdd.mem += sizeof(struct Dir);
  285.                                         }
  286.         
  287.                                         if(Flags & F_VERBOSE)
  288.                                             Printf("Dealocated %ld bytes\n\n", gdd.mem);
  289.                                     }
  290.                                 }
  291.     
  292.                                 Close(gdd.gd_Out);
  293.                             }
  294.                             else
  295.                             {
  296.                                 Printf("***Error Opening Destination File \'%s\'\n", gdd.ArgArray[FROM_FILE]);
  297.                                 gdd.gd_failureCode = 201;
  298.                             }
  299.     
  300.                             Close(gdd.gd_In);
  301.                         }
  302.                         else
  303.                         {
  304.                             Printf("***Error Opening Source File \'%s\'\n", gdd.ArgArray[FROM_FILE]);
  305.                             gdd.gd_failureCode = 201;
  306.                         }
  307.                         
  308.                         FreeArgs(rdargs);
  309.                     }
  310.                     else
  311.                     {
  312.                         if(!CheckAbort(gd))
  313.                         {
  314.                             Printf("%s\n%s\n", VersionString + 6, CopyRigthString);
  315.                         }
  316.                         else
  317.                             gdd.gd_failureCode = 200;
  318.                     }
  319.                     CloseLibrary(gdd.gd_UtilityBase);
  320.                 }
  321.                 else
  322.                     gdd.gd_failureCode = 21;
  323.                 CloseLibrary(gdd.gd_DOSBase);
  324.             }
  325.             else
  326.                 gdd.gd_failureCode = 20;
  327. #ifdef _M68020
  328.         }
  329.         else
  330.             gdd.gd_failureCode = 10;
  331. #endif
  332.     }
  333.     /* If running from WorkBench do nothing      */
  334.     else
  335.     {
  336.         gdd.gd_failureCode = 1;
  337.         
  338.         WaitPort (&(gdd.gd_Process->pr_MsgPort));
  339.         gdd.gd_wbMsg = (struct WBStartup *) GetMsg (&gdd.gd_Process->pr_MsgPort);
  340.  
  341.         Forbid();
  342.         ReplyMsg((struct Message *)gdd.gd_wbMsg);
  343.     }
  344.     gdd.gd_Process->pr_Result2 = gdd.gd_failureCode;
  345.     return(gdd.gd_failureLevel);
  346. }
  347.  
  348. /*
  349.  *
  350.  *
  351.  */
  352. BOOL PassOne(struct GlobalData *gd, ULONG Flags)
  353. {
  354.     REGISTER struct Dir *DirNode;
  355.     REGISTER struct SubDir *SubDirNode;
  356.  
  357.     REGISTER WORD i = 0;
  358.  
  359.     char *dir;
  360.     char *subdir;
  361.     char *olddir = "";
  362.     char *oldsubdir = "";
  363.     LONG filesize;
  364.  
  365.     FPrintf(gd->gd_Out,"@database \"AMINET\"\n");
  366.  
  367.     if(Flags & F_VERBOSE)
  368.     {
  369.         Printf("Pass One\n");
  370.     }
  371.  
  372.     DirNode = NULL;
  373.     SubDirNode = NULL;
  374.  
  375.     FPrintf(gd->gd_Out,"@NODE Main \"AmiNet Root Directory\"\n");
  376.  
  377.     FGets(gd->gd_In, gd->gd_string, 100);
  378.     while(gd->gd_string[0] == '|')
  379.     {
  380.         if(!(Flags & F_NOTITLE))
  381.         {
  382.  
  383.             if(i < gd->ArgArray[TITLEROW])
  384.             {
  385.                 FPuts(gd->gd_Out, gd->gd_string+1);
  386.                 i++;
  387.             }
  388.         }
  389.         FGets(gd->gd_In, gd->gd_string, 100);
  390.     }
  391.  
  392.     if(!(Flags & F_NOTITLE))
  393.         FPuts(gd->gd_Out, "\n");
  394.  
  395.     do
  396.     {
  397.         if(!(Flags & F_NOSIZE))
  398.         {
  399.             if(gd->gd_string[gd->ArgArray[SIZECOL] + 3] == '?')
  400.                 filesize = -1;
  401.             else
  402.             {
  403.                 Flags &= ~F_POINT;
  404.                 filesize = 0;
  405.  
  406.                 for(i = gd->ArgArray[SIZECOL]; i < gd->ArgArray[SIZECOL] + 3; i++)
  407.                     if(isnum(gd->gd_string[i]))
  408.                         filesize = SMult32(filesize, 10) + (gd->gd_string[i] - '0');
  409.                     else if(gd->gd_string[i] == '.')
  410.                         Flags |= F_POINT;
  411.  
  412.                 if(gd->gd_string[i] ==  'M')
  413.                 {
  414.                     filesize <<= 10;
  415.                     if(Flags & F_POINT)
  416.                         filesize = SDivMod32(filesize, 10);
  417.                 }
  418.             }
  419.         }
  420.  
  421.         dir = gd->gd_string + gd->ArgArray[DIRCOL];
  422.         dir[10] = 0;
  423.         subdir = FilePart(dir);
  424.  
  425.         if(dir == subdir)
  426.             Flags |= F_NOSUB;
  427.         else
  428.             Flags &= ~F_NOSUB;
  429.  
  430.         if(dir[0] == ' ')
  431.             Flags |= F_NODIR;
  432.         else
  433.             Flags &= ~F_NODIR;
  434.  
  435.         if(!(Flags & F_NODIR))
  436.         {
  437.             if(Flags & F_NOSUB)
  438.             {
  439.                 while(subdir[0] != ' ')
  440.                 subdir++;
  441.                 subdir[0] = 0;
  442.             }
  443.             else
  444.                 *(subdir-1) = 0;
  445.             
  446.             if(Strnicmp(olddir, dir, 5L))
  447.             {
  448.                 if(DirNode != NULL)
  449.                 {
  450.                     FPrintf(gd->gd_Out,"@{\"  %-5s  \" link %s}", DirNode->dir_name, DirNode->dir_name);
  451.                     if(!(Flags & F_NOSTATS))
  452.                     {
  453.                         FPrintf(gd->gd_Out, "      %5ld     %5ld     " , DirNode->dir_subcount, DirNode->dir_count);
  454.                         PrintSize(gd, DirNode->dir_size, DirNode->dir_ignore);
  455.                     }
  456.                     else
  457.                         FPuts(gd->gd_Out, "\n");
  458.                 }
  459.                 else
  460.                     if(!(Flags & F_NOHEAD))
  461.                         FPuts(gd->gd_Out, "                 subdirs    files      size\n"
  462.                                           "-------------------------------------------------\n");
  463.  
  464.                 if( (DirNode = (struct Dir *)AllocMem(sizeof(struct Dir), MEMF_CLEAR)) == NULL)
  465.                 {
  466.                     gd->gd_failureCode = 100;
  467.                     return(FALSE);
  468.                 }
  469.  
  470.                 gd->mem += sizeof(struct Dir);
  471.  
  472.                 for(i = 0; dir[i], i < 5; i ++)
  473.                     DirNode->dir_name[i] =  dir[i];
  474.                 DirNode->dir_name[i] =0;
  475.  
  476.                 if(gd->root_firstdir != NULL)
  477.                     gd->root_lastdir->dir_next = DirNode;
  478.                 else
  479.                     gd->root_firstdir = DirNode;
  480.                 gd->root_lastdir = DirNode;
  481.                 gd->root_dircount++;
  482.  
  483.                 olddir = DirNode->dir_name;
  484.                 oldsubdir = "";
  485.             }
  486.  
  487.             DirNode->dir_count++;
  488.             if(filesize != -1)
  489.                 DirNode->dir_size += filesize;
  490.             else
  491.                 DirNode->dir_ignore = TRUE;
  492.  
  493.             if(!(Flags &  F_NOSUB))
  494.             {
  495.                 if(Strnicmp(oldsubdir, subdir, 5))
  496.                 {
  497.                     if(CheckAbort(gd))
  498.                         return(FALSE);
  499.  
  500.                     if((SubDirNode = (struct SubDir *)AllocMem(sizeof(struct SubDir), MEMF_CLEAR)) == NULL)
  501.                     {
  502.                         gd->gd_failureCode = 100;
  503.                         return(FALSE);
  504.                     }
  505.  
  506.                     gd->mem += sizeof(struct SubDir);
  507.  
  508.                     for(i = 0; dir[i], i < 5; i ++)
  509.                         SubDirNode->sub_name[i] =  subdir[i];
  510.                     SubDirNode->sub_name[i] =0;
  511.  
  512.                     if(DirNode->dir_firstsub != NULL)
  513.                         DirNode->dir_lastsub->sub_next = SubDirNode;
  514.                     else
  515.                         DirNode->dir_firstsub = SubDirNode;
  516.                     DirNode->dir_lastsub = SubDirNode;
  517.                     DirNode->dir_subcount++;
  518.                     gd->root_subcount++;
  519.  
  520.                     oldsubdir = SubDirNode->sub_name;
  521.  
  522.                     if(Flags & F_VERBOSE)
  523.                     {
  524.                         Printf("Found Dir    : %s  \n"
  525.                                "Found Sub-Dir: %s  M\r", DirNode->dir_name, SubDirNode->sub_name);
  526.                     }
  527.                 }
  528.  
  529.                 SubDirNode->sub_count++;
  530.                 if(filesize != -1)
  531.                     SubDirNode->sub_size += filesize;
  532.                 else
  533.                     SubDirNode->sub_ignore = TRUE;
  534.             }
  535.             else
  536.             {
  537.                 Flags |= F_FIXSUB;
  538.                 DirNode->dir_pending++;
  539.                 gd->total_pending++;
  540.             }
  541.         }
  542.         else                                           
  543.         {
  544.             Flags |= F_FIXDIR;
  545.             gd->root_pending++;
  546.             gd->total_pending++;
  547.             dir[10] = ' ';
  548.             FPuts(gd->gd_Out, gd->gd_string);
  549.         }
  550.  
  551.         if(filesize != -1)
  552.             gd->root_size += filesize;
  553.         else
  554.             gd->root_ignore = TRUE;
  555.         gd->root_count++;
  556.  
  557.     }while(FGets(gd->gd_In, gd->gd_string, 100));
  558.  
  559.     if(DirNode != NULL)
  560.     {
  561.         FPrintf(gd->gd_Out,"@{\"  %-5s  \" link %s}", DirNode->dir_name, DirNode->dir_name);
  562.  
  563.         if(!(Flags & F_NOSTATS))
  564.         {
  565.             FPrintf(gd->gd_Out, "      %5ld     %5ld     ", DirNode->dir_subcount, DirNode->dir_count);
  566.             PrintSize(gd, DirNode->dir_size, DirNode->dir_ignore);
  567.         }
  568.         else
  569.             FPuts(gd->gd_Out, "\n");
  570.     }
  571.  
  572.     if(!(Flags & F_NOTOTAL))
  573.     {
  574.         FPrintf(gd->gd_Out, "\nTotal:  %ld dirs, %ld subdirs, %ld files, size ", gd->root_dircount, gd->root_subcount, gd->root_count);
  575.         PrintSize(gd, gd->root_size, gd->root_ignore);
  576.     }
  577.     FPuts(gd->gd_Out, "@ENDNODE\n\n");
  578.  
  579.  
  580.     if( gd->total_pending && (Flags & F_VERBOSE))
  581.     {
  582.         Printf("\n\nFound(s) %ld file(s) without ", gd->total_pending);
  583.  
  584.         if(Flags & F_FIXDIR)
  585.         {
  586.             Printf("directory");
  587.             if(Flags & F_FIXSUB)
  588.                 Printf(" and/or ");
  589.         }
  590.         if(Flags & F_FIXSUB)
  591.             Printf("subdirectory");
  592.  
  593.         if(gd->root_pending)
  594.             Printf(".\nAdded files to root directory (%ld)", gd->root_pending);
  595.  
  596.         Printf(".\n\nEntering FIX mode (Pass Two may take a while).M\r");
  597.  
  598.     }
  599.  
  600.     return(TRUE);
  601. }
  602.  
  603. /*
  604.  *
  605.  *
  606.  */
  607. BOOL PassTwo(struct GlobalData *gd, ULONG Flags)
  608. {
  609.     REGISTER struct Dir *DirNode;
  610.     REGISTER struct SubDir *SubDirNode;
  611.  
  612.     REGISTER WORD i;
  613.  
  614.  
  615.     if(Flags & F_VERBOSE)
  616.         Printf("\n\n\nPass Two\n");
  617.  
  618.     if(gd->total_pending)
  619.     {
  620.         Seek(gd->gd_In, 0, OFFSET_BEGINNING);
  621.         FGets(gd->gd_In, gd->gd_string, 80);
  622.  
  623.         /* Skip index header.                                 */
  624.         while(gd->gd_string[0] == '|')
  625.             FGets(gd->gd_In, gd->gd_string, 100);
  626.  
  627.         if((Flags & F_VERBOSE) && gd->root_pending)
  628.             Printf("Skipping root directory files (%ld)\n", gd->root_pending);
  629.  
  630.         gd->total_pending -= gd->root_pending;
  631.  
  632.         /* Skip files w/o dir/subdir.                         */
  633.         for(i = 0; i < gd->root_pending; i++)
  634.             FGets(gd->gd_In, gd->gd_string,100);
  635.     }
  636.  
  637.     DirNode = gd->root_firstdir;
  638.     while(DirNode != NULL)
  639.     {
  640.         if(Flags & F_VERBOSE)
  641.             Printf("Creating Node: %s  M\n",DirNode->dir_name);
  642.  
  643.         FPrintf(gd->gd_Out, "@NODE %s \"%s Directory\"\n\n", DirNode->dir_name,DirNode->dir_name);
  644.  
  645.         if(gd->total_pending)
  646.         {
  647.             if((Flags & F_VERBOSE) && DirNode->dir_pending)
  648.                 Printf("Adding directory \"%s\" files (%ld)\n", DirNode->dir_name, DirNode->dir_pending);
  649.  
  650.             gd->total_pending -=  DirNode->dir_pending;
  651.             for(i = 0; i < DirNode->dir_pending; i++)
  652.             {
  653.                 FPuts(gd->gd_Out, gd->gd_string);
  654.                 FGets(gd->gd_In, gd->gd_string, 100);
  655.             }
  656.             
  657.             for(; i < DirNode->dir_count; i++)
  658.                 FGets(gd->gd_In, gd->gd_string, 100);
  659.         }
  660.  
  661.         if (CheckAbort(gd))
  662.             return(FALSE);
  663.  
  664.         if(!(Flags & F_NOHEAD))
  665.             FPuts(gd->gd_Out, "               files       size\n"
  666.                               "-------------------------------------------------\n");
  667.  
  668.         SubDirNode = DirNode->dir_firstsub;
  669.         while(SubDirNode != NULL)
  670.         {
  671.             FPrintf(gd->gd_Out, "@{\"  %-5s  \" link %s-%s}", SubDirNode->sub_name, DirNode->dir_name, SubDirNode->sub_name);
  672.             if(!(Flags & F_NOSTATS))
  673.             {
  674.                 FPrintf(gd->gd_Out, "    %5ld     ", SubDirNode->sub_count);
  675.                 PrintSize(gd, SubDirNode->sub_size, SubDirNode->sub_ignore);
  676.             }
  677.             else
  678.                 FPuts(gd->gd_Out, "\n");
  679.             SubDirNode = SubDirNode->sub_next;
  680.         }
  681.  
  682.         if(!(Flags & F_NOTOTAL))
  683.         {
  684.             FPrintf(gd->gd_Out, "\nTotal:  %5ld subdirs, %5ld files, size ", DirNode->dir_subcount, DirNode->dir_count);
  685.             PrintSize(gd, DirNode->dir_size, DirNode->dir_ignore);
  686.         }
  687.         FPuts(gd->gd_Out, "@ENDNODE\n\n");
  688.  
  689.         DirNode = DirNode->dir_next;
  690.     }
  691.  
  692.     return(TRUE);
  693. }
  694.  
  695. /*
  696.  *
  697.  *
  698.  */
  699. BOOL PassThree(struct GlobalData *gd, ULONG Flags)
  700. {
  701.     REGISTER struct Dir *DirNode;
  702.     REGISTER struct SubDir *SubDirNode;
  703.  
  704.     REGISTER WORD i;
  705.  
  706.  
  707.     if(Flags & F_VERBOSE)
  708.         Printf("\n\nPass Three\n");
  709.  
  710.     Seek(gd->gd_In, 0, OFFSET_BEGINNING);
  711.     FGets(gd->gd_In, gd->gd_string, 80);
  712.  
  713.     /* Skip index header                                   */
  714.     while(gd->gd_string[0] == '|')
  715.         FGets(gd->gd_In, gd->gd_string, 100);
  716.  
  717.     if((Flags & F_VERBOSE) && gd->root_pending)
  718.         Printf("Skipping root directory files (%ld)\n", gd->root_pending);
  719.  
  720.     /* Skip files w/o dir/subdir                           */
  721.     for(i = 0; i < gd->root_pending; i++)
  722.         FGets(gd->gd_In, gd->gd_string,100);
  723.  
  724.     DirNode = gd->root_firstdir;
  725.     while(DirNode != NULL)
  726.     {
  727.         if((Flags & F_VERBOSE) && DirNode->dir_pending)
  728.             Printf("Skipping directory \"%s\" files (%ld)\n", DirNode->dir_name, DirNode->dir_pending);
  729.  
  730.         /* Skip files with dir and w/o subdir              */
  731.         for(i = 0; i < DirNode->dir_pending; i++)
  732.             FGets(gd->gd_In, gd->gd_string, 100);
  733.  
  734.         SubDirNode = DirNode->dir_firstsub;
  735.         while(SubDirNode != NULL)
  736.         {
  737.             if(Flags & F_VERBOSE)
  738.             {
  739.                 Printf("Working on Node : %s  \n"
  740.                        "Creating Sub-Dir: %s  M\r", DirNode->dir_name, SubDirNode->sub_name);
  741.             }
  742.  
  743.             if(CheckAbort(gd))
  744.                 return(FALSE);
  745.  
  746.             FPrintf(gd->gd_Out, "@NODE %s-%s \"%s/%s SubDirectory\"\n\n", DirNode->dir_name, SubDirNode->sub_name, DirNode->dir_name, SubDirNode->sub_name);
  747.  
  748.             for(i = 0; i < SubDirNode->sub_count; i++)
  749.             {
  750.                 FPuts(gd->gd_Out, gd->gd_string);
  751.                 FGets(gd->gd_In, gd->gd_string, 100);
  752.             }
  753.  
  754.             if(!(Flags & F_NOTOTAL))
  755.             {
  756.                 FPrintf(gd->gd_Out, "\nTotal:  %5ld files, size ", SubDirNode->sub_count);
  757.                 PrintSize(gd, SubDirNode->sub_size, SubDirNode->sub_ignore);
  758.             }
  759.             FPuts(gd->gd_Out, "@ENDNODE\n\n");
  760.  
  761.             SubDirNode = SubDirNode->sub_next;
  762.         }
  763.  
  764.         DirNode = DirNode->dir_next;
  765.  
  766.     }
  767.  
  768.     return(TRUE);
  769. }
  770.  
  771.  
  772. /*
  773.  * Function to check for CTRL-C break.
  774.  */
  775. BOOL CheckAbort(struct GlobalData *gd)
  776. {
  777.     if(SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  778.     {
  779.         Printf("\n\n***User Abort\n");
  780.         gd->gd_failureCode = 200;
  781.         return(TRUE);
  782.     }
  783.     return(FALSE);
  784. }
  785.  
  786. /*
  787.  * Print (write to file) the size of an item (root, dir, subdir, file).
  788.  * Scale format in order to make it smaller and more readable
  789.  * (1024KByte-> 1M, 1024MByte -> 1GByte)
  790.  */
  791. VOID PrintSize(struct GlobalData *gd, LONG size, BOOL ignore)
  792. {
  793.     /* Exact or aproximate size ?                                    */
  794.     if(ignore)
  795.         FPutC(gd->gd_Out, '>');
  796.     else
  797.         FPutC(gd->gd_Out, '=');
  798.  
  799.     if(!(size & 0xFFFFFC00))            /* Size < 1MByte (1024)        */
  800.         FPrintf(gd->gd_Out, "%5ldK\n", size);
  801.     else if(!(size & 0xFFF00000))        /* Size < 1Gbyte (1048576)    */
  802.         FPrintf(gd->gd_Out, "%3ld.%01ldM\n", size >> 10, SDivMod32((size & 0x000003FF), 100));
  803.     else
  804.         FPrintf(gd->gd_Out, "%3ld.%-02ldG\n", size >> 20, SDivMod32((size & 0x000FFFFF), 10000));
  805. }
  806.